home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / Samples / SprocketExamples / DroneZone / DroneZone Sources / DZInput.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-07-14  |  15.2 KB  |  573 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        DZInput.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     File Ownership:
  11.  
  12.         DRI:                xxx put dri here xxx
  13.  
  14.         Other Contact:        xxx put other contact here xxx
  15.  
  16.         Technology:            xxx put technology here xxx
  17.  
  18.     Writers:
  19.  
  20.         (sjb)    Steve Bollinger
  21.  
  22.     Change History (most recent first):
  23.  
  24.         <14>     6/18/98    sjb        InputSprocket.h comes from <> place
  25. */
  26.  
  27. /*
  28.  *    File:        DZInput.c
  29.  *
  30.  *    Contents:    Handles input devices.
  31.  *
  32.  *    Copyright © 1996 Apple Computer, Inc.
  33.  */
  34.  
  35. #include <TextUtils.h>
  36.  
  37. #define USE_OLD_INPUT_SPROCKET_LABELS 0
  38. #define USE_OLD_ISPNEED_STRUCT 0
  39. #include <InputSprocket.h>
  40.  
  41. #include "DZGame.h"
  42. #include "DZInput.h"
  43. #include "DZResource.h"
  44.  
  45. #define USE_MOUSE_AND_KEYBOARD 1
  46.  
  47. #define        ISpSymmetricAxisToFloat(axis)    ((((float) axis) - kISpAxisMiddle) / (kISpAxisMaximum-kISpAxisMiddle))
  48. #define        ISpAsymmetricAxisToFloat(axis)    (((float) axis) / (kISpAxisMaximum))
  49.  
  50. /*
  51. enum {
  52.     kElement_Fire,
  53.     kElement_Pause,
  54.     kElement_ShowHUD,
  55.     kElement_ShowFPS,
  56.     kElement_Turn,
  57.     kElement_COUNT
  58. };
  59. */
  60.  
  61. enum
  62. {
  63.     kNeed_Fire,
  64.     kNeed_Roll,
  65.     kNeed_Pitch,
  66.     kNeed_Throttle,
  67.     kNeed_ThrottleUp,
  68.     kNeed_ThrottleDown,
  69.     kNeed_ThrottleFull,
  70.     kNeed_ThrottleZero,
  71.     kNeed_InertialDampers,
  72.     kNeed_Yaw,
  73.     kNeed_YawLeft,
  74.     kNeed_YawCenter,
  75.     kNeed_YawRight,
  76.     kNeed_ShowHUD,
  77.     kNeed_ShowFPS,
  78.     kNeed_ShowThrottle,
  79.     kNeed_ShowVelocity,
  80.     kNeed_InstantStop,
  81.     kNeed_Pause,
  82.     kNeed_COUNT
  83. };
  84.  
  85. #define        kNeedsVersion        1
  86.  
  87. static Boolean                    gInputActive = false;
  88. static ISpElementListReference    gInputEventList = NULL;
  89. static ISpElementListReference    gInputHoldDownEventList = NULL;
  90. static ISpElementListReference    gInputYawEventList = NULL;
  91. static ISpElementListReference    gInputThrottleEventList = NULL;
  92. static ISpElementReference        gInputElement[kNeed_COUNT] = {NULL, NULL, NULL, NULL, NULL};
  93.  
  94.  
  95. /* =============================================================================
  96.  *        Input_Init (external)
  97.  *
  98.  *    Initializes the Input stuff.
  99.  * ========================================================================== */
  100. void Input_Init(
  101.     void)
  102. {
  103.     UInt32        itr;
  104.                     
  105.     ISpNeed        needs[kNeed_COUNT] =
  106.     {
  107.         { "\pFire", kIconSuiteID_Fire, 0, 0,
  108.             kISpElementKind_Button,
  109.             kISpElementLabel_Btn_Fire,
  110.             0, 0, 0, 0
  111.         },
  112.         { "\pRoll", kIconSuiteID_Roll, 0, 0,
  113.             kISpElementKind_Axis,
  114.             kISpElementLabel_Axis_Roll,
  115.             0, 0, 0, 0
  116.         },
  117.         { "\pPitch", kIconSuiteID_Pitch, 0, 0,
  118.             kISpElementKind_Axis,
  119.             kISpElementLabel_Axis_Pitch,
  120.             0, 0, 0, 0
  121.         },
  122.         { "\pThrottle", kIconSuiteID_Throttle, 0, 1,
  123.             kISpElementKind_Axis,
  124.             kISpElementLabel_Axis_Throttle,
  125.             kISpNeedFlag_Axis_AlreadyButton | kISpNeedFlag_Axis_Asymetric, 0, 0, 0
  126.         },
  127.         { "\pIncrease Throttle", kIconSuiteID_ThrottleUp, 0, 1,
  128.             kISpElementKind_Button,
  129.             kISpElementLabel_None,
  130.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  131.         },
  132.         { "\pDecrease Throttle", kIconSuiteID_ThrottleDown, 0, 1,
  133.             kISpElementKind_Button,
  134.             kISpElementLabel_None,
  135.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  136.         },
  137.         { "\pThrottle Max", kIconSuiteID_ThrottleMax, 0, 1,
  138.             kISpElementKind_Button,
  139.             kISpElementLabel_None,
  140.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  141.         },
  142.         { "\pThrottle Min", kIconSuiteID_ThrottleMin, 0, 1,
  143.             kISpElementKind_Button,
  144.             kISpElementLabel_None,
  145.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  146.         },
  147.         { "\pInertial Dampers", kIconSuiteID_InertialDampers, 0, 0,
  148.             kISpElementKind_Button,
  149.             kISpElementLabel_None,
  150.             0, 0, 0, 0
  151.         },
  152.         { "\pRudder", kIconSuiteID_Rudder, 0, 2,
  153.             kISpElementKind_Axis,
  154.             kISpElementLabel_Axis_Rudder,
  155.             kISpNeedFlag_Axis_AlreadyButton, 0, 0, 0
  156.         },
  157.         { "\pYaw Left", kIconSuiteID_RudderLeft, 0, 2,
  158.             kISpElementKind_Button,
  159.             kISpElementLabel_Btn_LookLeft,
  160.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  161.         },
  162.         { "\pYaw Center", kIconSuiteID_RudderCenter, 0, 2,
  163.             kISpElementKind_Button,
  164.             kISpElementLabel_None,
  165.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  166.         },
  167.         { "\pYaw Right", kIconSuiteID_RudderRight, 0, 2,
  168.             kISpElementKind_Button,
  169.             kISpElementLabel_Btn_LookRight,
  170.             kISpNeedFlag_Button_AlreadyAxis, 0, 0, 0
  171.         },
  172.         { "\pShow HUD", kIconSuiteID_ShowHUD, 0, 0,
  173.             kISpElementKind_Button,
  174.             kISpElementLabel_None,
  175.             0, 0, 0, 0
  176.         },
  177.         { "\pShow FPS", kIconSuiteID_ShowFPS, 0, 0,
  178.             kISpElementKind_Button,
  179.             kISpElementLabel_None,
  180.             0, 0, 0, 0
  181.         },
  182.         { "\pShow Throttle", kIconSuiteID_ShowThrottle, 0, 0,
  183.             kISpElementKind_Button,
  184.             kISpElementLabel_None,
  185.             0, 0, 0, 0
  186.         },
  187.         { "\pShow Velocity", kIconSuiteID_ShowVelocity, 0, 0,
  188.             kISpElementKind_Button,
  189.             kISpElementLabel_None,
  190.             0, 0, 0, 0
  191.         },
  192.         { "\pInstant Stop", kIconSuiteID_InstantStop, 0, 0,
  193.             kISpElementKind_Button,
  194.             kISpElementLabel_None,
  195.             0, 0, 0, 0
  196.         },
  197.         { "\pPause", kIconSuiteID_Pause, 0, 0,
  198.             kISpElementKind_Button,
  199.             kISpElementLabel_Btn_PauseResume,
  200.             0, 0, 0, 0
  201.         }
  202.     };
  203.     
  204.     // Get the names for the needs
  205.     for (itr = 0; itr < kNeed_COUNT; itr++)
  206.         GetIndString(needs[itr].name,        kStrListID_NeedsNames,    itr+1);
  207.     
  208.     #if USE_MOUSE_AND_KEYBOARD
  209.         
  210.         // Enable the mouse
  211.         ISpDevices_ActivateClass (kISpDeviceClass_Mouse);
  212.         
  213.         // Enable the keyboard
  214.         ISpDevices_ActivateClass (kISpDeviceClass_Keyboard);
  215.     #endif
  216.     
  217.     // Set our virtual elements
  218.       ISpElement_NewVirtualFromNeeds(kNeed_COUNT, needs, gInputElement, 0);
  219.     
  220.     // Autoconfigure our virtual elements based on our needs
  221.     ISpInit(kNeed_COUNT, needs, gInputElement, ' dz ', kNeedsVersion, 0, kSetListID, 0);
  222.       
  223.      // Build two lists of elements, which we'll poll for events 
  224.      // the 'hold down' list reports both up and down events
  225.     ISpElementList_New(0, NULL, &gInputEventList, 0);
  226.     ISpElementList_New(0, NULL, &gInputHoldDownEventList, 0);
  227.     
  228.     // Add the virtual elements one at a time so we can assign a refcon
  229.     ISpElementList_AddElements(gInputHoldDownEventList, kInputEvent_Fire_On,1, &gInputElement[kNeed_Fire]);
  230.  
  231.     ISpElementList_AddElements(gInputHoldDownEventList, kInputEvent_InertialDampers_On,
  232.                                                                             1, &gInputElement[kNeed_InertialDampers]);
  233.     
  234.     ISpElementList_AddElements(gInputEventList, kInputEvent_InstantStop,     1, &gInputElement[kNeed_InstantStop]);
  235.  
  236.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowHUD,         1, &gInputElement[kNeed_ShowHUD]);
  237.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowFPS,         1, &gInputElement[kNeed_ShowFPS]);
  238.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowThrottle,     1, &gInputElement[kNeed_ShowThrottle]);
  239.     ISpElementList_AddElements(gInputEventList, kInputEvent_ShowVelocity,     1, &gInputElement[kNeed_ShowVelocity]);
  240.     
  241.     ISpElementList_AddElements(gInputEventList, kInputEvent_Pause,             1, &gInputElement[kNeed_Pause]);
  242.  
  243.  
  244.       // Build our list of elements used for the rudder (yaw) when from buttons
  245.     ISpElementList_New(0, NULL, &gInputYawEventList, 0);
  246.     
  247.     // Add the virtual elements one at a time so we can assign a refcon
  248.     ISpElementList_AddElements(gInputYawEventList, kNeed_YawLeft, 1, &gInputElement[kNeed_YawLeft]);
  249.     ISpElementList_AddElements(gInputYawEventList, kNeed_YawCenter, 1, &gInputElement[kNeed_YawCenter]);
  250.     ISpElementList_AddElements(gInputYawEventList, kNeed_YawRight, 1, &gInputElement[kNeed_YawRight]);
  251.  
  252.  
  253.       // Build our list of elements used for the throttle when from buttons
  254.     ISpElementList_New(0, NULL, &gInputThrottleEventList, 0);
  255.     
  256.     // Add the virtual elements one at a time so we can assign a refcon
  257.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleUp, 1, &gInputElement[kNeed_ThrottleUp]);
  258.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleDown, 1, &gInputElement[kNeed_ThrottleDown]);
  259.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleFull, 1, &gInputElement[kNeed_ThrottleFull]);
  260.     ISpElementList_AddElements(gInputThrottleEventList, kNeed_ThrottleZero, 1, &gInputElement[kNeed_ThrottleZero]);
  261.  
  262.      // Start off suspended (because the game is stopped)
  263.     ISpSuspend();
  264. }
  265.  
  266.  
  267. /* =============================================================================
  268.  *        Input_Exit (external)
  269.  *
  270.  *    Prepares for exit.
  271.  * ========================================================================== */
  272. void Input_Exit(
  273.     void)
  274. {
  275.     if (gInputActive)
  276.     {
  277.         Input_Activate(false);
  278.     }
  279.     
  280.     if (gInputEventList != NULL)
  281.     {
  282.         ISpElementList_Dispose(gInputEventList);
  283.         gInputEventList = NULL;
  284.     }
  285.     
  286.     if (gInputHoldDownEventList != NULL)
  287.     {
  288.         ISpElementList_Dispose(gInputHoldDownEventList);
  289.         gInputHoldDownEventList = NULL;
  290.     }
  291.     
  292.      ISpStop();
  293.      
  294.     ISpElement_DisposeVirtual(kNeed_COUNT, gInputElement);
  295. }
  296.  
  297.  
  298. /* =============================================================================
  299.  *        Input_Configure (external)
  300.  *
  301.  *    Show the configuration dialog.
  302.  * ========================================================================== */
  303. void Input_Configure(
  304.     void)
  305. {
  306.      ISpConfigure(NULL);
  307. }
  308.  
  309. #if 0
  310. /* =============================================================================
  311.  *        Input_GetState (external)
  312.  *
  313.  *    This routine handles the elements that are polled.  It returns in outXTurn
  314.  *    and outYTurn the "turn" controls in the ±1 range.
  315.  * ========================================================================== */
  316. void Input_GetState(
  317.     float*                outXTurn,
  318.     float*                outYTurn)
  319. {
  320.     ISpMovementData        movementData;
  321.     double                xTurn = 0.0;
  322.     double                yTurn = 0.0;
  323.     
  324.     if (gInputActive)
  325.     {
  326.         // Get the data
  327.         ISpElement_GetComplexState(
  328.                 gInputElement[kNeed_Turn],
  329.                 sizeof(ISpMovementData),
  330.                 &movementData);
  331.         
  332.         // Turn 'em into ±1 float range
  333.         xTurn = movementData.xAxis;
  334.         xTurn -= kISpAxisMiddle;
  335.         xTurn /= kISpAxisMaximum-kISpAxisMiddle;
  336.         
  337.         yTurn = movementData.yAxis;
  338.         yTurn -= kISpAxisMiddle;
  339.         yTurn /= kISpAxisMaximum-kISpAxisMiddle;
  340.         yTurn *= -1;    // reverse axis
  341.     }
  342.     
  343.     // Return the values
  344.     *outXTurn = xTurn;
  345.     *outYTurn = yTurn;
  346. }
  347. #endif
  348.  
  349. float Input_GetRoll (void)
  350. {
  351.     ISpAxisData            axisValue = kISpAxisMiddle;
  352.     
  353.     (void) ISpElement_GetSimpleState(gInputElement[kNeed_Roll], &axisValue);
  354.     return ISpSymmetricAxisToFloat (axisValue);
  355. }
  356.  
  357. float Input_GetPitch (void)
  358. {
  359.     ISpAxisData            axisValue = kISpAxisMiddle;
  360.     
  361.     (void) ISpElement_GetSimpleState(gInputElement[kNeed_Pitch], &axisValue);
  362.     return (-1.0 * ISpSymmetricAxisToFloat (axisValue));
  363. }
  364.  
  365. float Input_GetYaw (void)
  366. {
  367.     static    float        gYawValue = 0.0;
  368.     static    Boolean        gYawInitalized = false;
  369.     
  370.     float                yawValue = gYawValue;
  371.     OSStatus            error = noErr;
  372.     ISpAxisData            axisValue;
  373.     Boolean                wasEvent;
  374.     ISpElementEvent        event;
  375.     
  376.     // should probably put the initialization check somewhere else, so does not do it every time
  377.     if (!gYawInitalized)
  378.     {
  379.         (void) ISpElement_GetSimpleState(gInputElement[kNeed_Yaw], &axisValue);
  380.         gYawValue = ISpSymmetricAxisToFloat (axisValue);
  381.  
  382.         gYawInitalized = true;
  383.     }
  384.         
  385.     // we check the axis, to see if IT was moved, if so, we use that value
  386.     wasEvent = false;
  387.     error = ISpElement_GetNextEvent (gInputElement[kNeed_Yaw], sizeof (event), &event, &wasEvent);
  388.     if (!error && wasEvent)
  389.     {
  390.         error = ISpElement_GetSimpleState(gInputElement[kNeed_Yaw], &axisValue);
  391.         if (!error) yawValue = ISpSymmetricAxisToFloat (axisValue);
  392.  
  393.         ISpElement_Flush(gInputElement[kNeed_Yaw]);
  394.     }
  395.     else do
  396.     {
  397.         error = ISpElementList_GetNextEvent (gInputYawEventList, sizeof (event), &event, &wasEvent);
  398.         
  399.         // only process valid keydown events (all the yaw events ignore button ups)
  400.         if (wasEvent && !error && (event.data == kISpButtonDown))
  401.         {
  402.             UInt32 keyFunction = event.refCon; // because we set it this way
  403.             switch (keyFunction)
  404.             {
  405.                 case kNeed_YawLeft:
  406.                     yawValue -= 0.1;
  407.                     if (yawValue < -1.0) yawValue = -1.0; 
  408.                     break;
  409.                 case kNeed_YawCenter:
  410.                     yawValue = 0.0;
  411.                     break;
  412.                 case kNeed_YawRight:
  413.                     yawValue += 0.1;
  414.                     if (yawValue > 1.0) yawValue = 1.0; 
  415.                     break;
  416.             }
  417.         }
  418.     }
  419.     while (wasEvent && !error);
  420.     
  421.     gYawValue = yawValue;
  422.     
  423.     return yawValue;
  424. }
  425.  
  426. float Input_GetThrottle (void)
  427. {
  428.     static    float        gThrottleValue = 0.0;
  429.     static    Boolean        gThrottleInitialized = false;
  430.     
  431.     float                throttleValue = gThrottleValue;
  432.     OSStatus            error = noErr;
  433.     ISpAxisData            axisValue;
  434.     Boolean                wasEvent;
  435.     ISpElementEvent        event;
  436.     
  437.     // should probably put the initialization check somewhere else, so does not do it every time
  438.     if (!gThrottleInitialized)
  439.     {
  440.         (void) ISpElement_GetSimpleState(gInputElement[kNeed_Throttle], &axisValue);
  441.         gThrottleValue = ISpAsymmetricAxisToFloat (axisValue);
  442.  
  443.         gThrottleInitialized = true;
  444.     }
  445.     
  446.     // we check the axis, to see if IT was moved, if so, we use that value
  447.     wasEvent = false;
  448.     error = ISpElement_GetNextEvent (gInputElement[kNeed_Throttle], sizeof (event), &event, &wasEvent);
  449.     if (!error && wasEvent)
  450.     {
  451.         error = ISpElement_GetSimpleState(gInputElement[kNeed_Throttle], &axisValue);
  452.         if (!error) throttleValue = ISpAsymmetricAxisToFloat (axisValue);
  453.  
  454.         ISpElement_Flush(gInputElement[kNeed_Throttle]);
  455.     }
  456.     else do
  457.     {
  458.         error = ISpElementList_GetNextEvent (gInputThrottleEventList, sizeof (event), &event, &wasEvent);
  459.         
  460.         // only process valid keydown events (all the throttle events ignore button ups)
  461.         if (wasEvent && !error && (event.data == kISpButtonDown))
  462.         {
  463.             UInt32 keyFunction = event.refCon; // because we set it this way
  464.             switch (keyFunction)
  465.             {
  466.                 case kNeed_ThrottleUp:
  467.                     throttleValue += 0.05;
  468.                     if (throttleValue > 1.0) throttleValue = 1.0; 
  469.                     break;
  470.                 case kNeed_ThrottleDown:
  471.                     throttleValue -= 0.05;
  472.                     if (throttleValue < 0.0) throttleValue = 0.0; 
  473.                     break;
  474.                 case kNeed_ThrottleFull:
  475.                     throttleValue = 1.0;
  476.                     break;
  477.                 case kNeed_ThrottleZero:
  478.                     throttleValue = 0.0;
  479.                     break;
  480.             }
  481.         }
  482.     }
  483.     while (wasEvent && !error);
  484.     
  485.     gThrottleValue = throttleValue;
  486.     
  487.     return throttleValue;
  488. }
  489.  
  490.  
  491.  
  492. /* =============================================================================
  493.  *        Input_GetEvent (external)
  494.  *
  495.  *    This routine handles the elements that are event-based.  It returns an
  496.  *    event code indicating which button has gone down.  Note that we ignore
  497.  *    button-up transitions.  Should be called repeatedly until it return
  498.  *    kInputEvent_None.
  499.  * ========================================================================== */
  500. TInputEvent Input_GetEvent(
  501.     void)
  502. {
  503.     OSErr                err;
  504.     TInputEvent            result = kInputEvent_None;
  505.     ISpElementEvent        event;
  506.     Boolean                gotEvent;
  507.     
  508.     if (gInputActive)
  509.     {
  510.         err = ISpElementList_GetNextEvent(gInputHoldDownEventList, sizeof(event), &event, &gotEvent);
  511.         if (err == noErr && gotEvent)
  512.         {
  513.             result = (TInputEvent) event.refCon;
  514.             if (event.data == kISpButtonUp)
  515.                 result += 1;    // Note: we rely on off being on+1 (ie kInputEvent_InertialDampers_Off == kInputEvent_InertialDampers_On + 1)
  516.         }
  517.         else
  518.         {
  519.             err = ISpElementList_GetNextEvent(gInputEventList, sizeof(event), &event, &gotEvent);
  520.             
  521.             if (err == noErr && gotEvent && event.data == kISpButtonDown)
  522.                 result = (TInputEvent) event.refCon;
  523.         }
  524.     }
  525.     
  526.     return result;
  527. }
  528.  
  529.  
  530. /* =============================================================================
  531.  *        Input_Activate (external)
  532.  *
  533.  *    On deactivation, we suspend InputSprocket.  On activation we resume it and
  534.  *    flush the event queue.  We only allow activation when the game is in "Play"
  535.  *    state.
  536.  * ========================================================================== */
  537. void Input_Activate(
  538.     Boolean                inActivate)
  539. {
  540.     Boolean                doActivate;
  541.     
  542.     doActivate = inActivate;
  543.     if (doActivate && Game_GetState() != kGameState_Playing)
  544.     {
  545.         doActivate = false;
  546.     }
  547.     
  548.     if (gInputActive != doActivate)
  549.     {
  550.         gInputActive = doActivate;
  551.         
  552.          if (gInputActive)
  553.          {
  554.              #if USE_MOUSE_AND_KEYBOARD
  555.                  HideCursor();
  556.              #endif
  557.              
  558.              ISpResume();
  559.              ISpElementList_Flush(gInputEventList);
  560.          }
  561.          else
  562.          {
  563.              ISpSuspend();
  564.              
  565.              #if USE_MOUSE_AND_KEYBOARD
  566.                  ShowCursor();
  567.              #endif
  568.          }
  569.     }
  570. }
  571.  
  572.  
  573.